#ifndef _TIMER_16BIT_H_
#define _TIMER_16BIT_H_

#include <avr/io.h>
#include <avr/interrupt.h>
#include "../../../../bit/bit.h"
#include "../../../Component.h"

namespace Hardware
{
namespace Avr
{
	typedef struct TIMER_16BIT_CONFIG
	{
		unsigned char outputCompareA : 2;
		unsigned char outputCompareB : 2;
		unsigned char forceA : 1;
		unsigned char forceB : 1;
		unsigned char waveformMode : 4;
		unsigned char noiseCanceler : 1;
		unsigned char captureEdgeSelect : 1;
		unsigned char clockSelect : 3;
		unsigned long int count : 16;
		unsigned long int outputCountA : 16;
		unsigned long int outputCountB : 16;
		unsigned long int inputCapture : 16;
		unsigned char captureInterrupt : 1;
		unsigned char compareAInterrupt : 1;
		unsigned char compareBInterrupt : 1;
		unsigned char overflowInterrupt : 1;
		
	} Timer16BitConfig;

	typedef struct TIMER_16BIT_DATA
	{
	} Timer16BitData;

	class Timer16Bit : public Component<Timer16BitConfig, Timer16BitData>
	{
		public :

		enum OutputCompareMode
		{
			NormalPortOperation = 0x00,
			ToggleOnCompare = 0x01,
			ClearOnCompare = 0x02,
			SetOnCompare = 0x03
		};
		enum ClockPrescale
		{
			NoClock = 0x00,
			Prescale1 = 0x01,
			Prescale8 = 0x02,
			Prescale64 = 0x03,
			Prescale256 = 0x04,
			Prescale1024 = 0x05,
			PrescaleExtFalling = 0x06,
			PrescaleExtRising = 0x07
		};
		enum WaveFormModes
		{
			NormalWaveform=0x00,
			PWM_PhaseCorrect8=0x01,
			PWM_PhaseCorrect9=0x02,
			PWM_PhaseCorrect10=0x03,
			CTC_Mode =0x04,
			FastPWM8 = 0x05,
			FastPWM9 = 0x06,
			FastPWM10=0x07,
			PWM_PhaseFreqCorrect=0x08,
			PWM_PhaseFreqCorrect2=0x09,
			PWM_PhaseCorrect=0x0A,
			CTC_Mode2 = 0x0B,
			ReservedMode = 0x0C,
			FastPWMMode1 = 0x0D,
			FastPWMMode2 = 0x0E
		};

		Timer16Bit(){}
		Timer16Bit(Timer16BitConfig c){configuration=c;}

		void config()
		{
			TCCR1A = (TCCR1A & 0x3F) | (configuration.outputCompareA<<6);
			TCCR1A = (TCCR1A & 0xCF) | (configuration.outputCompareB<<4);
			//force output compare
			TCCR1A = SetBit(TCCR1A, FOC1A, configuration.forceA);
			TCCR1A = SetBit(TCCR1A, FOC1B, configuration.forceB);
			//set waveform mode
			TCCR1A = (TCCR1A & 0xFC) 
				| (configuration.waveformMode & 0x03);
			TCCR1B = (TCCR1B & ~(0x03<<3))
				 | ((configuration.waveformMode & 0x0C)<<1);
			//set noise canceller
			TCCR1B = SetBit(TCCR1B, ICNC1, configuration.noiseCanceler);
			//set capture select
			TCCR1B = SetBit(TCCR1B, ICES1,
				 configuration.captureEdgeSelect);
			//set clock select
			TCCR1B = (TCCR1B & 0xF8) | configuration.clockSelect;
			//set count
			TCNT1H = (unsigned char) configuration.count >> 8;
			TCNT1L = (unsigned char) configuration.count & 0x00FF;
			//set compare A
			OCR1AH = (unsigned char) configuration.outputCountA>>8;
			OCR1AL = (unsigned char) configuration.outputCountA&0x00FF;
			//set compare B
			OCR1BH = (unsigned char) configuration.outputCountB>>8;
			OCR1BL = (unsigned char) configuration.outputCountB&0x00FF;
			//set input capture register
			ICR1H = (unsigned char) configuration.inputCapture>>8;
			ICR1L = (unsigned char) configuration.inputCapture&0x00FF;
			//set capture interrupt enable
			TIMSK = SetBit(TIMSK, TICIE1,
				 configuration.captureInterrupt);
			//set compare a interrupt
			TIMSK = SetBit(TIMSK, OCIE1A,
				configuration.compareAInterrupt);
			//set compare b interrupt
			TIMSK = SetBit(TIMSK, OCIE1B,
				configuration.compareBInterrupt);
			//set overflow interrupt
			TIMSK = SetBit(TIMSK, TOIE1, 
				configuration.overflowInterrupt);

		}

	};
}}





#endif
